package router

import (
	"context"
	"fmt"
	"net/http"
	"os/signal"
	"syscall"
	"time"

	"service/app/api"
	_ "service/docs"
	"service/global"

	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"
	swaggerfiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
)

// gin-swagger middleware
// swagger embed files

/**  约束路由列表调用*/
type IFnRegistRoutes = func(pubRoute *gin.RouterGroup, authRoute *gin.RouterGroup)

func JoinRoutes(fn IFnRegistRoutes) {
	if fn == nil {
		return
	}
	routes = append(routes, fn)
}

var (
	routes []IFnRegistRoutes
)

func InitRouter(middleware gin.HandlerFunc) {

	// signal创建 监听上下文信道,监听指定信号,监听异常退出的底层信号
	ctx, ctxCancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	// 停止ctx
	defer ctxCancel()
	// 处理
	r := gin.Default()
	// 前綴
	var prefix string = viper.GetString("service.prefix")
	pubRoute := r.Group(fmt.Sprintf("%s/pub", prefix))
	authRoues := r.Group(prefix)

	// 中间件
	authRoues.Use(middleware)

	InitPlatformBaseRoutes()
	// 循环注册路由
	for _, IFnRegistRoutes := range routes {
		IFnRegistRoutes(pubRoute, authRoues)
	}

	port := viper.GetString("service.port")
	if port == "" {
		port = "38281"
	}
	server := &http.Server{Addr: "[::]:" + port, Handler: r}

	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))

	// 本系统所有API列表
	r.GET(prefix+"/syslist", api.Getlist(r))

	// ctx运行项目,并行运行服务器
	go func() {
		global.Logger.Info(fmt.Sprintf("成功开启服务器 在 %s端口", port))
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			global.Logger.Error(fmt.Printf("server is not running - error %s", err.Error()))
			return
		}
	}()

	// 收到取出信号时,处理关闭.
	<-ctx.Done()
	// context处理延时关闭,返回一个函数
	{
		ctx, serverShutDown := context.WithTimeout(context.Background(), 5*time.Second)
		defer serverShutDown()
		// 如果不执行,手动执行
		if err := server.Shutdown(ctx); err != nil {
			global.Logger.Error(fmt.Printf("server ShutDown error - %s", err.Error()))
			return
		}
		// 输出成功日志
		global.Logger.Info("成功关闭服务器~!")
	}

}

/** 加载路由器
 */
func InitPlatformBaseRoutes() {
	UserRoutesInit()
	AdminRouteInit()
	MenuRouteInit()
	PmRouterCreate()
	RoleRoutesInit()
	ApmRouteInit()
}
